package com.myk.game.gobangchess.rooms.prerooms;

import com.myk.game.gobangchess.CustomBottom;
import com.myk.game.gobangchess.Room;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.signs.ColorSign;
import com.myk.game.gobangchess.signs.TextSign;
import com.myk.game.gobangchess.signs.TitleSign;
import com.myk.game.gobangchess.utils.GridsUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 兵分棋
 */
public class ArmyFormRoom extends Room {

    private List<Integer> blackHandChessList;//黑方手中持有棋子，上线4个且元素不同，3红：火， 4蓝：风， 5黄：山，  6绿：林
    private List<Integer> whiteHandChessList;//白方手中持有棋子，上线4个且元素不同 3红：火， 4蓝：风， 5黄：山，  6绿：林

    public ArmyFormRoom(String roomName) {
        super(roomName, "江柯设计，包含可控随机性、无偏博弈、和连锁特效等元素的落子棋。", "兵分棋", GridsUtils.createEmptyGrids(15,15), true, true);
    }

    @Override
    public String getRuleText() {
        return "{{《兵分棋》Aetheria游戏规则@scale=1.3@color=#FF000000}}\n" +
                "{{一、棋盘与棋子设定：@style=i@color=#FF000000}}\n" +
                "\t\t1.采用 15×15 方格棋盘。\n" +
                "\t\t2.对局双方初始各持有 “{{风@color=#FF0000AA}}、{{林@color=#FF00AA00}}、{{火@color=#FFAA0000}}、{{山@color=#FFAAAA00}}” 四种属性棋子各 1 枚。\n" +
                "\t\t3.初始棋盘正中心会放置一枚随机属性的棋子。\n" +
                "{{二、回合行动规则：@style=i@color=#FF000000}}\n" +
                "\t\t1.双方交替进行回合行动。玩家需先选定棋盘上1枚棋子直斜相邻的1处空格，再从己方持有的棋子中随机挑选 1 枚放置在选定位置。\n" +
                "\t\t2.当己方将最后 1 枚棋子放置到棋盘后，可立即重新获得 “{{风@color=#FF0000AA}}、{{林@color=#FF00AA00}}、{{火@color=#FFAA0000}}、{{山@color=#FFAAAA00}}” 4 枚棋子。\n" +
                "\t\t3.玩家在任何时刻，均可先补满 “{{风@color=#FF0000AA}}、{{林@color=#FF00AA00}}、{{火@color=#FFAA0000}}、{{山@color=#FFAAAA00}}” 这 4 枚棋子，再执行其他操作。\n" +
                "{{三、特殊规则说明：@style=i@color=#FF000000}}\n" +
                "\t\t1.棋子一旦落在棋盘上，即成为双方共有资源，不再区分归属。\n" +
                "\t\t2.落下棋子后会根据棋子属性触发特殊效果：：\n" +
                "\t\t\t\t{{风：@color=#FF0000AA}}可以选择1枚直斜相邻的棋子往直斜方向空格移动1格。\n" +
                "\t\t\t\t{{林：@color=#FF00AA00}}可以选择1枚直向相邻的棋子王直线方向空格复制1枚。\n" +
                "\t\t\t\t{{火：@color=#FFAA0000}}可以选择1枚斜向相邻的棋子移出棋盘。\n" +
                "\t\t\t\t{{山：@color=#FFAAAA00}}不会收到其它棋子特效的影响。\n" +
                "\t\t3.落子后或者执行特效后，需检查 3×3 范围内是否存在 5 枚特定同属性元素棋子相接，呈直轴对称排列的特殊形状。属性对应的特殊形状如下：\n" +
                "\t\t\t\t{{风：V字@color=#FF0000AA}}，{{林：十字@color=#FF00AA00}}，{{火：X字@color=#FFAA0000}}，{{山：T字@color=#FFAAAA00}}。\n" +
                "\t\t4.每形成1个特殊形状己方获得 1 分，除组成该特殊形状的所有棋子，然后己方可以再次落子。\n" +
                "{{四、胜利条件：@style=i@color=#FF000000}}\n" +
                "\t\t1.率先累积获得5分的一方获胜。\n" +
                "\t\t2.落子操作填满棋盘的一方获胜。";
    }

    @Override
    public String getGameInfo() {
        signList.clear();

        for (int i = 0; i < curGrids.length; i++) {
            for (int j = 0; j < curGrids[i].length; j++) {
                if (curGrids[i][j] == 0){
                    if (isCanMove(i,j)){
                        signList.add(new ColorSign(getIndex(i,j),ColorCost.GRAY_TRANSLUCENT ));
                    }
                }
                //绘制棋子上的文字
                else {
                    signList.add(new TextSign(getIndex(i,j),getTextByValue(curGrids[i][j]),ColorCost.BLACK));
                }
            }
        }
        //绘制手上持有棋子
        if (blackHandChessList != null && whiteHandChessList != null){
            float aClipY = (curGrids.length + 0.2f) / curGrids.length;
            for (int i = 0; i < blackHandChessList.size(); i++) {
                int value = blackHandChessList.get(i);
                String text = getTipTextByValue(value);
                String color = getColorByValue(value);
                float bClipX = (i + 0.5f) / curGrids[0].length;;
                signList.add(new TitleSign(bClipX, aClipY, 0, text, color, 0.3f));
            }
            for (int i = 0; i < whiteHandChessList.size(); i++) {
                int value = whiteHandChessList.get(i);
                String text = getTipTextByValue(value);
                String color = getColorByValue(value);
                float wClipX = (curGrids[0].length - 4 + i + 0.5f) / curGrids[0].length;
                signList.add(new TitleSign(wClipX, aClipY, 0, text, color, 0.3f));
            }
        }
        return super.getGameInfo();
    }

    private String getColorByValue(int value) {
        switch (value) {
            case 3:
                return "#FFAA0000";
            case 4:
                return "#FF0000AA";
            case 5:
                return "#FFAAAA00";
            case 6:
                return "#FF00AA00";
            default:
                return "";
        }
    }

    private String getTipTextByValue(int value) {
        switch (value) {
            case 3:
                return "火(X)";
            case 4:
                return "风(V)";
            case 5:
                return "山(T)";
            case 6:
                return "林(+)";
            default:
                return "";
        }
    }

    private String getTextByValue(int value) {
        switch (value) {
            case 3:
                return "火";
            case 4:
                return "风";
            case 5:
                return "山";
            case 6:
                return "林";
            default:
                return "";
        }
    }

    @Override
    protected void onStartPrepare() {
        resetHandChessList(1);
        resetHandChessList(2);
        curGrids[curGrids.length/2][curGrids[0].length/2] = (int) (Math.random() * 4 + 3);
        super.onStartPrepare();
    }

    @Override
    protected void prepareInGameButtons() {
        if (player_black != player_white) {
            player_black.registerCustomBottom(new CustomBottom(this, "重置属性", p -> resetHandChessList(1)));
            player_white.registerCustomBottom(new CustomBottom(this, "重置属性", p -> resetHandChessList(2)));
        }
        else {
            player_black.registerCustomBottom(new CustomBottom(this, "重置属性", p -> resetHandChessList(cur)));
        }
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (isCanMove(row,col)){
            if (value == 1){
                int index = (int) (Math.random()*blackHandChessList.size());
                int chess = blackHandChessList.get(index);
                curGrids[row][col] = chess;
                blackHandChessList.remove(index);
                if (blackHandChessList.size() == 0){
                    resetHandChessList(1);
                }
                noticeWhiteMove();
            }
            else if (value == 2){
                int index = (int) (Math.random()*whiteHandChessList.size());
                int chess = whiteHandChessList.get(index);
                curGrids[row][col] = chess;
                whiteHandChessList.remove(index);
                if (whiteHandChessList.size() == 0){
                    resetHandChessList(2);
                }
                noticeBlackMove();
            }
        }
    }

    // 重置持有棋子
    private void resetHandChessList(int cur){
        List<Integer> list = new ArrayList<>();
        list.add(4);
        list.add(6);
        list.add(3);
        list.add(5);
        if (cur == 1){
            blackHandChessList = list;
        }
        else if (cur == 2){
            whiteHandChessList = list;
        }
        noticeAllRefreshGameInfo();
    }

    //该位置可以落子
    /**
     * 判断指定位置是否可以落子（增加范围限定和边界检查）
     * @param row 行索引
     * @param col 列索引
     * @return 是否可以落子
     */
    private boolean isCanMove(int row, int col) {

        // 目标位置已有棋子，不能落子
        if (curGrids[row][col] != 0) {
            return false;
        }

        // 定义相邻位置的偏移量（8个方向：上下左右+对角线）
        int[][] offsets = {
                {-1, 0}, {1, 0},   // 上下
                {0, -1}, {0, 1},   // 左右
                {-1, -1}, {-1, 1}, // 左上、右上
                {1, -1}, {1, 1}    // 左下、右下
        };

        // 检查所有相邻位置是否在棋盘范围内且有棋子
        for (int[] offset : offsets) {
            int newRow = row + offset[0];
            int newCol = col + offset[1];

            // 检查相邻位置是否在棋盘范围内
            if (newRow >= 0 && newRow < curGrids.length && newCol >= 0 && newCol < curGrids[0].length) {
                // 相邻位置有棋子，允许落子
                if (curGrids[newRow][newCol] != 0) {
                    return true;
                }
            }
        }

        return false;
    }
}
